/*
** 作者：TheBadZhang
** 创建时间：2003??
** 最后修改时间：看文件
** 文件名：image.h
** 用途：image 类，主要的图像处理玩意儿
*/


#include "xege.h"
namespace xege {


	// 从文件加载图片，支持的文件格式如下，路径采用 UTF-8 编码（大概）
	// BMP, GIF, JPEG, LBM, PCX, PNG, PNM, SVG, TGA, TIFF, WEBP, XCF, XPM, XV
	void IMAGE::getImageFromFile (std::string path) {
		SDL_Surface* temp = IMG_Load (path.c_str ());

		if (temp == nullptr) {
			// 错误
			SDL_Log ("getImageFromFile Failed: %s", SDL_GetError ());
		} else {
			// 成功
			sPic = SDL_ConvertSurfaceFormat (temp, SDL_PIXELFORMAT_RGBA8888, 0);
			this -> w = sPic -> w;
			this -> h = sPic -> h;
			if (sPic == nullptr) {
				// 错误
				SDL_Log ("ConvertSurfaceFormat Failed: %s", SDL_GetError ());
			} else {
				// 啊啊啊啊啊啊，这里我忘记初始化了，导致卷积器putPixel的时候越界了！！
				rPic = SDL_CreateSoftwareRenderer (sPic);
				tPic = SDL_CreateTextureFromSurface (rPic, sPic);
				// SDL_SetRenderDrawBlendMode (rPic, SDL_RENDERER_SOFTWARE);
				if (rPic == nullptr)
						SDL_Log ("Create Software Renderer error: %s", SDL_GetError ());
			}
		}

		SDL_FreeSurface (temp);
	}
	// 从像素序列中获得图像
	void IMAGE::getImageFromPixels (uint w, uint h, color_t* pixels) {
		// init ();

		uint32_t rmask = 0xff000000,gmask = 0x00ff0000,bmask = 0x0000ff00,amask = 0x000000ff;
		this -> w = w;
		this -> h = h;
		/* SDL interprets each pixel as a 32-bit number, so our masks must depend
		on the endianness (byte order) of the machine */
		

		if (pixels == nullptr) {
			// 
			sPic = SDL_CreateRGBSurface(0, w, h, 32, rmask, gmask, bmask, amask);
			if (sPic == nullptr) {
				SDL_Log("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
				// closeGraph ();
			}
		} else {
			sPic = SDL_CreateRGBSurfaceFrom(pixels, w, h, 32, w * 4 , rmask, gmask, bmask, amask);
			if (sPic == nullptr) {
				SDL_Log("SDL_CreateRGBSurfaceFrom() failed: %s", SDL_GetError());
				// closeGraph ();
			}
		}
		// SDL_LockSurface (sPic);
		// id ++;
		rPic = SDL_CreateSoftwareRenderer (sPic);
		tPic = SDL_CreateTextureFromSurface (rPic, sPic);
		// SDL_SetRenderDrawBlendMode (rPic, SDL_RENDERER_SOFTWARE);
		if (rPic == nullptr)
				SDL_Log ("Create Software Renderer error: %s", SDL_GetError ());
	}
	// 保存为 PPM 格式的图片
	void IMAGE::savePPM (std::string path) {
		std::ifstream in (path);
		if (in.is_open ()) {
			SDL_Log ("ERROR: file has alreaady exited");
		}
	}
	// 复制图片（基础）
	void IMAGE::copyImageB (IMAGE &pic) {
		w = pic.getWidth ();
		h = pic.getHeight ();
		setFGColor (pic.getFGColor ());
		setBGColor (pic.getBGcolor ());
		// setWindow (pic.getWindow  ());
		setOffset (pic.getOffset ());
		sPic = SDL_CreateRGBSurface (0, w, h, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
		SDL_BlitSurface (pic.getSurface (), nullptr, sPic, nullptr);
		rPic = SDL_CreateSoftwareRenderer (sPic);
		tPic = SDL_CreateTextureFromSurface (rPic, sPic);
	}

	// 更新图像（好像没有用的来着？）
	void IMAGE::update (void) {
		SDL_RenderPresent (rPic);
		SDL_RenderCopy (rPic, tPic, nullptr, nullptr);
		// SDL_RenderCopy (rPic, Window.getTexture (), NULL, NULL);
		// SDL_UpdateWindowSurface (Window.getWindow ());
	}
	// 从数据中读取像素信息，创建 IMAGE
	IMAGE::IMAGE (WINDOW &dstWindow, uint w, uint h, color_t* pixels): Window (dstWindow), pWindow (&dstWindow) {
		getImageFromPixels (w, h, pixels);
	}
	// 从数据中读取像素信息，创建 IMAGE
	IMAGE::IMAGE (WINDOW* dstWindow, uint w, uint h, color_t* pixels): Window (*dstWindow), pWindow (dstWindow) {
		getImageFromPixels (w, h, pixels);
	}
	// 从文件中获取图片
	IMAGE::IMAGE (WINDOW &dstWindow, std::string path): Window (dstWindow), pWindow (&dstWindow) {
		getImageFromFile (path);
	}
	// 从文件中获取图片
	IMAGE::IMAGE (WINDOW* dstWindow, std::string path): Window (*dstWindow), pWindow (dstWindow) {
		getImageFromFile (path);
	}
	// 从 surface 中获取图片
	IMAGE::IMAGE (WINDOW &dstWindow, SDL_Surface* src): Window (dstWindow), pWindow (&dstWindow) {
		getImage (src);
	}
	// 从 surface 中获取图片
	IMAGE::IMAGE (WINDOW* dstWindow, SDL_Surface* src): Window (*dstWindow), pWindow (dstWindow) {
		getImage (src);
	}
	// 从 IMAGE 中获取图片
	IMAGE::IMAGE (IMAGE &pic) : Window (pic.getWindow ()), pWindow (pic.getPWindow ()){
		copyImageB (pic);
	}
	// 从 IMAGE 中获取图片
	IMAGE::IMAGE (IMAGE* pic): Window (pic -> getWindow ()), pWindow (pic -> getPWindow ()) {
		copyImageB (*pic);
	}
	// 从 WINDOW 中获取图片
	// IMAGE (WINDOW &dstWindow): Window (dstWindow), pWindow (&dstWindow) {
		
	// }
	// 从 renderer 中获取图片
	// 从 texture 中获取图片
	IMAGE::~IMAGE (void) {
		// SDL_RenderPresent (rPic);
		IMG_Quit ();
		Mix_Quit ();
	}
	// 设置目标窗口
	void IMAGE::setWindow (WINDOW& dstWindow) {
		Window = dstWindow;
		pWindow = &dstWindow;
	}
	// 设置目标窗口
	void IMAGE::setWindow (WINDOW* dstWindow) {
		Window = *dstWindow;
		pWindow = dstWindow;
	}
	// 获得窗口
	WINDOW& IMAGE::getWindow  (void) { return Window;  }
	// 获得窗口
	WINDOW* IMAGE::getPWindow (void) { return pWindow; }
	
	// 从文件获取图片
	void IMAGE::getImage (std::string path) {
		getImageFromFile (path);
	}
	// void getImage (SDL_Renderer* renderer) {
	// 	void* pixels = new color_t [w*h];
	// 	SDL_RenderReadPixels(renderer, nullptr, SDL_PIXELFORMAT_RGBA8888, (void*)pixels, 32);
	// 	// getImageFromPixels (w, h, pixels);
	// 	SDL_Surface* p1 = SDL_CreateRGBSurfaceFrom((void*)pixels, w, h, 8, pitch, rmask, gmask, bmask, amask);
	// }
	// 从 surface 中获取图片
	void IMAGE::getImage (SDL_Surface* surface) {
		getImageFromPixels (surface -> w, surface -> h);
		SDL_BlitSurface (surface, nullptr, sPic, nullptr);
	}
	// 从 IMAGE 中获取图片
	void IMAGE::getImage (IMAGE* pic) {
		getImageFromPixels (pic -> getSurface () -> w, pic -> getSurface () -> h);
		SDL_BlitSurface (pic -> getSurface (), nullptr, sPic, nullptr);
	}
	// 从 IMAGE 中获取图片
	void IMAGE::getImage (IMAGE &pic) {
		getImageFromPixels (pic.getSurface () -> w, pic.getSurface () -> h);
		SDL_BlitSurface (pic.getSurface (), nullptr, sPic, nullptr);
	}
	// 从 IMAGE 中 copy 图片
	void IMAGE::copyImage (IMAGE &pic) {
		copyImageB (pic);
	}
	// 从 IMAGE 中 copy 图片
	void IMAGE::copyImage (IMAGE* pic) {
		copyImageB (*pic);
	}

	// void copyImage (SDL_Surface* surface) {
	// 	getImageFromPixels (surface -> w, surface -> h);
	// 	SDL_BlitSurface (surface, nullptr, sPic, nullptr);
	// }
	// void copyImage (IMAGE* pic) {
	// 	getImageFromPixels (pic -> getSurface () -> w, pic -> getSurface () -> h);
	// 	SDL_BlitSurface (pic -> getSurface (), nullptr, sPic, nullptr);
	// }
	// void copyImage (IMAGE &pic) {
	// 	getImageFromPixels (pic.getSurface () -> w, pic.getSurface () -> h);
	// 	SDL_BlitSurface (pic.getSurface (), nullptr, sPic, nullptr);
	// }


	// 从一个 IMAGE 的部分复制到 Window 的部分
	void IMAGE::putImageScaled (int x, int y, int w, int h) {
		RECT dstPicRect {x, y, w, h};
		SDL_BlitScaled (sPic, nullptr, Window.getSurface (), &dstPicRect);
	}
	// void putImageScaled (RECT dst = {0, 0, 0, 0}) {
	// 	SDL_BlitScaled (sPic, nullptr, Window.getSurface (), &dst);
	// }
	// 从一个 IMAGE 的部分复制到 Window 的部分
	void IMAGE::putImageScaled (RECT src, RECT dst) {
		SDL_BlitScaled (sPic, &src, Window.getSurface (), &dst);
	}
	// 从一个 IMAGE 的部分复制到 Window 的部分
	void IMAGE::putImage (int x, int y, int w, int h) {
		RECT dstPicRect {x, y, w, h};
		SDL_BlitSurface (sPic, nullptr, Window.getSurface (), &dstPicRect);
	}
	// 从一个 IMAGE 的部分复制到 Window 的部分
	void IMAGE::putImage (RECT src, RECT dst) {
		SDL_BlitSurface (sPic, &src, Window.getSurface (), &dst);
	}
	// 从一个 IMAGE 的部分复制到另一个 surface 的部分
	void IMAGE::putImage (SDL_Surface* surface) {
		SDL_BlitSurface (sPic, nullptr, Window.getSurface (), nullptr);
	}
	// putimage_rotation
	// putimage_flip
	// putimage_
	void IMAGE::update2 (void) {
		SDL_SetRenderTarget (Window.getRenderer (), tPic);
		SDL_RenderClear (Window.getRenderer ());
		// SDL_RenderCopy (Window.getRenderer ())
		SDL_SetRenderTarget (Window.getRenderer (), nullptr);
	// http://lazyfoo.net/tutorials/SDL/43_render_to_texture/index.php
	}

	// 文件路径，文件格式，图像质量（仅 JPG 文件）
	// 路径推荐英文，没有试过中文会怎么样
	void IMAGE::saveImage (std::string filepath, IMAGETYPE type, int quality) {
		if (filepath.size () == 0) {
			filepath = rand () + ".png";
		}
		switch (type) {
		case PNG:  IMG_SavePNG (sPic, filepath.c_str ());          break;
		case BMP:  SDL_SaveBMP (sPic, filepath.c_str ());          break;
		case JPG:  IMG_SaveJPG (sPic, filepath.c_str (), quality); break;
		// case WEBP: imgwe
		// case PPM: 
		default:   IMG_SavePNG (sPic, filepath.c_str ());
		}
	}

}  // 命名空间 xege 结尾
